<?php
/**
 * @description:
 * @author     : Geomen
 * @time       : 2018/12/3 11:52
 */


namespace App\Http\Controllers;


use App\Http\Resources\CrontabCollection;
use App\Models\FormId;
use App\Models\IpCrontab;
use App\Models\IpPingLog;
use App\Models\User;
use App\Models\UserHost;
use Illuminate\Http\Request;

class IpController extends Controller
{
    public function ping(Request $request)
    {
        $host      = e($request->input('host'));
        $port      = intval($request->input('port', 22));
        $transport = $request->input('transport', 'tcp');
        $timeout   = $request->input('timeout', 0.5);
        $time      = 0;

        IpPingLog::query()->create(['ping_host' => $host, 'port' => $port]);

        // 如果不是IPv4
        if (false === filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            // 如果是IPv6
            if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                $host = '[' . $host . ']';
            }
        }

        if (starts_with($host,'https')){
            $host = substr($host,8);
        }elseif (starts_with($host,'http')){
            $host = substr($host,7);
        }

        try {
            $time_start = self::microtime_float();
            $host = gethostbyname($host); // 这里如果挂了，说明服务器的DNS解析不给力，必须换
            if (starts_with($host, ['192.168.', '10.10.', '127.0.0.','100.'])){
                $ret = 0;
                $message = '不可用';
            }elseif (preg_match('/[A-Za-z]+/',$host)){

                $ret = 0;
                $message = '域名解析失败';
            }else {
                $fp = @stream_socket_client($transport . '://' . $host . ':' . $port, $errno, $errstr, $timeout);
                if (!$fp) {
                    $ret     = 0;
                    $message = '不可用';
                } else {
                    $ret     = 1;
                    $message = '可用';
                }
                @fclose($fp);
            }
            $time_end = self::microtime_float();
            $time = ceil(($time_end - $time_start) *1000);
            return response()->json(['status' => $ret, 'message' => $message,'time' => $time, 'host' => $host.':'.$port]);
        }
        catch (\Exception $e) {
            info($e);
            return response()->json(['status' => 0, 'message' => 'port close', 'time' => $time, 'host' => $host.':'.$port]);
        }
    }

    /**
     * 添加用户地址
     * @param Request $request
     *
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $this->validate($request, ['host' => 'required','open_id' => 'required'],[], ['host' => '地址']);
        $id = intval($request->input('id'));
        $host      = e($request->input('host'));
        $port      = intval($request->input('port', 22));
        $open_id   = $request->input('open_id');
        if (starts_with($host,'https')){
            $host = substr($host,8);
        }elseif (starts_with($host,'http')){
            $host = substr($host,7);
        }
        if ($id){
            $exists = UserHost::query()->where('host',$host)->where('open_id', $open_id)
                ->where('port', $port)->where('id', '<>', $id)->first();
            if ($exists) {
                if ($exists->is_del == 0) {
                    return $this->responseFail('已存在记录');
                }else{
                    $exists->delete();
                }
            }
            $info = UserHost::query()->findOrFail($id);
            $info->host = $host;
            $info->port = $port;
            if ($info->isDirty()){
                $crontab = IpCrontab::query()->where('user_host_id', $info->id)->where('open_id', $open_id)->first();
                if ($crontab) {
                    $crontab->check_result = 0;
                    $crontab->check_count = 0;
                    $crontab->save();
                }
                $info->save();
            }
            return $this->responseSuccess('编辑成功');
        }
        $info = UserHost::query()->firstOrCreate(compact('host','open_id','port'));
        if (!$info->wasRecentlyCreated){
            if ($info->is_del == 0) {
                return $this->responseFail('已存在记录');
            }
            $info->is_del = 0;
            $info->save();
        }
        return $this->responseSuccess();
    }

    /**
     * 获取用户添加的地址
     * @param Request $request
     *
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function getUserHost(Request $request)
    {
        $open_id   = $request->input('open_id');
        $list = UserHost::query()->where('open_id',$open_id)->where('is_del',0)
            ->withCount('crontab')->oldest('sort')->latest()->get();
        return $this->responseSuccess('',$list);
    }

    /**
     * 更新用户地址列表排序
     * @param Request $request
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     * @throws \Illuminate\Validation\ValidationException
     */
    public function setUserHostSort(Request $request)
    {
        $this->validate($request, ['ids' => 'required', 'open_id' => 'required']);
        $ids = e($request->input('ids'));
        $open_id = $request->input('open_id');
        $ida = explode(',', $ids);
        foreach ($ida as $key => $id){
            UserHost::query()->where('id', $id)->where('open_id', $open_id)->update(['sort' => $key]);
        }
        return $this->responseSuccess('排序成功');
    }

    /**
     * 删除用户地址
     *
     * @param Request $request
     *
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function delUserHost(Request $request)
    {
        $id = intval($request->input('id'));
        $res = UserHost::query()->where('id',$id)->update(['is_del' => 1]);
        if ($res){
            IpCrontab::query()->where('user_host_id',$id)->delete();
            return $this->responseSuccess('删除成功');
        }else{
            return $this->responseFail('删除失败');
        }
    }

    /**
     * 添加到定时任务列表
     *
     * @param Request $request
     *
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function addToCrontab(Request $request)
    {
        $id = intval($request->input('id'));
        $open_id = $request->input('open_id');
        $user = User::query()->where('open_id',$open_id)->firstOrFail();
        UserHost::query()->where('open_id',$open_id)->findOrFail($id);
        $crontabCount = IpCrontab::query()->where('open_id',$open_id)->count();
        if ($crontabCount >= $user->max_crontab){
            return $this->responseFail('添加失败,最多添加3个,需要更多请加微信');
        }
        $crontab = IpCrontab::query()->firstOrCreate(['user_host_id' => $id,'open_id' => $open_id]);
        if ($crontab->wasRecentlyCreated) {
            return $this->responseSuccess('添加成功');
        }
        return $this->responseFail('添加失败,已存在');
    }

    /**
     * 获取我的定时任务列表
     *
     * @param Request $request
     *
     * @return CrontabCollection
     */
    public function getCrontabList(Request $request)
    {
        $open_id = $request->input('open_id');
        $list = IpCrontab::query()->where('open_id',$open_id)->with('host')->oldest('sort')->latest()->get();
        return (new CrontabCollection($list))->additional(['meta' => [
            'form_id_total' => FormId::query()->where('open_id',$open_id)->where('expire_time','>',time())->count()
        ]]);
    }

    /**
     * 更新定时任务列表排序
     * @param Request $request
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     * @throws \Illuminate\Validation\ValidationException
     */
    public function setCrontabListSort(Request $request)
    {
        $this->validate($request, ['ids' => 'required', 'open_id' => 'required']);
        $ids = e($request->input('ids'));
        $open_id = $request->input('open_id');
        $ida = explode(',', $ids);
        foreach ($ida as $key => $id){
            IpCrontab::query()->where('id', $id)->where('open_id', $open_id)->update(['sort' => $key]);
        }
        return $this->responseSuccess('排序成功');
    }

    /**
     * 删除定时任务
     *
     * @param Request $request
     *
     * @return \Illuminate\Contracts\Routing\ResponseFactory|\Illuminate\Http\Response
     */
    public function delCrontabItem(Request $request)
    {
        $open_id = $request->input('open_id');
        $id = intval($request->input('id'));
        $res = IpCrontab::query()->where('id',$id)->where('open_id',$open_id)->delete();
        if ($res){
            return $this->responseSuccess('删除成功');
        }else{
            return $this->responseFail('删除失败');
        }
    }

    protected function microtime_float()
    {
        list($usec, $sec) = explode(" ", microtime());

        return ((float)$usec + (float)$sec);
    }
}